<?php
//优客365导航路由  2021-01-21
class Router
{
    static private $url_mode;  // 0 动态模式  1  //pathinfo 模式
    static private $var_controller;
    static private $var_module;
    static private $url_html_suffix;
    static private $url_pathinfo_depr;
    static private $default_module;
    static private $default_controller;
    static private $url_route; //路由
    static private $route; //路由
    static private $app_path;


    static private $subDomainVal;
    static private $subDomainDeploy;
    static private $domainSuffix;
    static private $subDomainRules;

    /**
     * 初始化方法
     * @param type $config
     */
    static public function init($config)
    {
        self::$url_mode = $config['URL_MODE'];
        self::$var_module = isset($config['VAR_MODULE']) ? $config['VAR_MODULE'] : 'm';
        self::$var_controller = isset($config['VAR_CONTROLLER']) ? $config['VAR_CONTROLLER'] : 'c';
        self::$url_html_suffix = isset($config['URL_HTML_SUFFIX']) ? $config['URL_HTML_SUFFIX'] : 'html';
        self::$default_module = isset($config['DEFAULT_MODULE']) ? $config['DEFAULT_MODULE'] : 'index';
        self::$default_controller = isset($config['DEFAULT_CONTROLLER']) ? $config['DEFAULT_CONTROLLER'] : 'index';
        self::$url_pathinfo_depr = isset($config['URL_PATHINFO_DEPR']) ? $config['URL_PATHINFO_DEPR'] : '/';
        self::$url_route = isset($config['URL_ROUTE']) ? $config['URL_ROUTE'] : '';
        self::$route = isset($config['ROUTE']) ? isset($config['ROUTE']['route']) ? $config['ROUTE']['route'] : '' : '';
        self::$app_path = isset($config['APP_PATH']) ? $config['APP_PATH'] : '';

        self::$subDomainDeploy = isset($config['ROUTE']) ? isset($config['ROUTE']['app_sub_domain_deploy']) ? $config['ROUTE']['app_sub_domain_deploy'] : false : false;
        self::$subDomainRules = isset($config['ROUTE']) ? isset($config['ROUTE']['app_sub_domain_rules']) ? $config['ROUTE']['app_sub_domain_rules'] : [] : [];
        self::$domainSuffix = isset($config['ROUTE']) ? isset($config['ROUTE']['app_domain_suffix']) ? $config['ROUTE']['app_domain_suffix'] : '' : '';
        self::$subDomainVal = self::getSubDomain();
    }

    /**
     * @return array|string[]
     * Description:获取url打包参数
     */
    static public function url()
    {
        // return self::getParamByPathinfo();

        switch (self::$url_mode) {
            //动态url传参 模式
            case 0:
                return self::getParamByDynamic();
                break;
            //pathinfo 模式
            case 1:
                return self::getParamByPathinfo();
                break;
        }

    }

    /**
     * @return array
     * Description:获取参数通过url传参模式
     */
    static private function getParamByDynamic()
    {
        $arr = empty($_SERVER['QUERY_STRING']) ? array() : explode('&', $_SERVER['QUERY_STRING']);

        $data = array(
            'module' => '',
            'controller' => '',
            'param' => array()
        );
        /*----如果绑定了子域名和模块则先判断绑定模块----start*/
        if (self::$subDomainDeploy) {
            $rules = self::$subDomainRules;
            if (isset($rules[$_SERVER['HTTP_HOST']])) { // 完整域名或者IP配置
                $rule = $rules[$_SERVER['HTTP_HOST']];
            } else {
                if (strpos(self::$domainSuffix, '.')) { // com.cn net.cn
                    $domain = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -3);
                } else {
                    $domain = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -2);
                }
                if (!empty($domain)) {
                    $subDomain = implode('.', $domain);
                    $domain2 = array_pop($domain); // 二级域名
                    if ($domain) { // 存在三级域名
                        $domain3 = array_pop($domain);
                    }
                    if (isset($rules[$subDomain])) { // 子域名
                        $rule = $rules[$subDomain];
                    } elseif (isset($rules['*.' . $domain2]) && !empty($domain3)) { // 泛三级域名
                        $rule = $rules['*.' . $domain2];
                    } elseif (isset($rules['*']) && !empty($domain2) && 'www' != $domain2) { // 泛二级域名
                        $rule = $rules['*'];
                    }
                }
            }

            if (!empty($rule)) {
                // 子域名部署规则 '子域名'=>array('模块名[/控制器名]','var1=a&var2=b');
                if (is_array($rule)) {
                    list($rule, $vars) = $rule;
                }
                $array = explode('/', $rule);
                // 模块绑定
                $data['module'] = array_shift($array);
            }
        }
        /*----如果绑定了子域名和模块则先判断绑定模块----end*/

        if (!empty($arr)) {
            $tmp = array();
            $part = array();
            foreach ($arr as $v) {
                $tmp = explode('=', $v);
                $tmp[1] = isset($tmp[1]) ? trim($tmp[1]) : '';
                $part[$tmp[0]] = $tmp[1];
            }


            if (isset($part[self::$var_module])) {
                $data['module'] = $part[self::$var_module];
                unset($part[self::$var_module]);
            }


            if (isset($part[self::$var_controller])) {
                $data['controller'] = $part[self::$var_controller];
                unset($part[self::$var_controller]);
            }

            switch ($_SERVER['REQUEST_METHOD']) {
                case 'GET':
                    unset($_GET[self::$var_controller], $_GET[self::$var_module]);
                    $data['param'] = array_merge($part, $_GET);
                    unset($_GET);
                    break;
                case 'POST':
                    unset($_POST[self::$var_controller], $_GET[self::$var_module]);
                    $data['param'] = array_merge($part, $_POST);
                    unset($_POST);
                    break;
                case 'HEAD':
                    break;
                case 'PUT':
                    break;
            }
        }

        return $data;
    }

    /**
     * @return array|string[]
     * Description:获取参数通过pathinfo模式
     */
    static private function getParamByPathinfo()
    {
        $request_url = urldecode(trim($_SERVER['REQUEST_URI'], '/'));
        if (!empty(self::$url_html_suffix)) {
            $urlHtmlSuffixStr = '.' . self::$url_html_suffix;
            if ($startSuffix = stripos($request_url, $urlHtmlSuffixStr)) {
                $request_url = substr($request_url, 0, $startSuffix) . substr($request_url, $startSuffix + strlen($urlHtmlSuffixStr));
            }
        }
        //使用了路由解析
        $reg_status = false;
        if ((!empty(self::$route[self::$subDomainVal])) && is_array(self::$route[self::$subDomainVal])) {

            foreach (self::$route[self::$subDomainVal] as $reg => $v) {
                $reg1 = preg_replace('#(\{\d*\})#', '(.*)', $reg);
                if (preg_match("#^$reg1$#", $request_url, $match)) {
                    //插件插件目录识别
                    if (strpos($v, ':')) {
                        $arr = explode(':', $v);
                        self::$app_path = $arr[0];  //存在应用目录
                        $v = $arr[1];
                    }
                    $reg_status = true;
                    $newArr = array_splice($match, 1);

                    $find = [];
                    $replace = [];
                    foreach ($newArr as $k2 => $v2) {
                        //将参数组装成实际路径
                        $k2 = $k2 + 1;
                        array_push($find, "{" . $k2 . "}");
                        array_push($replace, $v2);
                    }
                    $part0 = str_replace($find, $replace, trim($v));
                    break;
                }

            }

        }

        if ($reg_status == false) {
            $part0 = $request_url;
        }
        //去掉part0后面如果存在?=***则先去掉
        if (strpos($part0, '?') === false) {
            $part0 = explode(self::$url_pathinfo_depr, trim($part0, '/'));
        } else {
            $part0 = substr($part0, 0, stripos($part0, '?'));
            $part0 = explode(self::$url_pathinfo_depr, trim($part0, '/'));
        }
        $part1 = empty($_SERVER['QUERY_STRING']) ? array() : explode('&', urldecode($_SERVER['QUERY_STRING']));
        $path_param = [];
        foreach ($part1 as $k => $v) {
            $arr = explode('=', $v);
            if (count($arr) == 2) {
                $path_param[$arr[0]] = $arr[1];
            } else {
                $path_param = [];
            }
        }
        $part = str_replace('.' . self::$url_html_suffix, '', $part0);

        $data = [
            'module' => '',
            'controller' => '',
        ];
        if (!empty($part)) {
            krsort($part);
            //如果不是路由的情况再使用子域名绑定判断，如果存在则改变module
            /*----如果绑定了子域名和模块则先判断绑定模块----start*/
            if ((!$reg_status) && self::$subDomainDeploy) {
                $rules = self::$subDomainRules;
                if (isset($rules[$_SERVER['HTTP_HOST']])) { // 完整域名或者IP配置
                    $rule = $rules[$_SERVER['HTTP_HOST']];
                } else {
                    if (strpos(self::$domainSuffix, '.')) { // com.cn net.cn
                        $domain = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -3);
                    } else {
                        $domain = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -2);
                    }
                    if (!empty($domain)) {
                        $subDomain = implode('.', $domain);
                        $domain2 = array_pop($domain); // 二级域名
                        if ($domain) { // 存在三级域名
                            $domain3 = array_pop($domain);
                        }
                        if (isset($rules[$subDomain])) { // 子域名
                            $rule = $rules[$subDomain];
                        } elseif (isset($rules['*.' . $domain2]) && !empty($domain3)) { // 泛三级域名
                            $rule = $rules['*.' . $domain2];
                        } elseif (isset($rules['*']) && !empty($domain2) && 'www' != $domain2) { // 泛二级域名
                            $rule = $rules['*'];
                        }
                    }
                }
                if (!empty($rule)) {
                    if (is_array($rule)) {
                        list($rule, $vars) = $rule;
                    }
                    $array = explode('/', $rule);
                    // 模块绑定的取子域名对应的为模块
                    $data['module'] = array_shift($array);
                    // 变量第一个为控制器
                    $data['controller'] = array_pop($part);
                } else {
                    //如果没有子域名则还是用原来的
                    $data['module'] = array_pop($part);
                    $data['controller'] = array_pop($part);
                }
                ksort($part);
                $part = array_values($part);
                $tmp = [];

                if (count($part) > 0) {
                    foreach ($part as $k => $v) {
                        if ($k % 2 == 0) {
                            $tmp[$v] = isset($part[$k + 1]) ? $part[$k + 1] : '';
                        }
                    }
                }
                switch ($_SERVER['REQUEST_METHOD']) {
                    case 'GET':

                        $data = array_merge($tmp, $_GET, $data, $path_param);

                        break;
                    case 'POST':

                        $data = array_merge($tmp, $_POST, $data, $path_param);

                        break;
                    case 'HEAD':
                        break;
                    case 'PUT':
                        break;
                }
            } else {
                $data['module'] = array_pop($part);
                $data['controller'] = array_pop($part);
                ksort($part);
                $part = array_values($part);
                $tmp = [];

                if (count($part) > 0) {
                    foreach ($part as $k => $v) {
                        if ($k % 2 == 0) {
                            $tmp[$v] = isset($part[$k + 1]) ? $part[$k + 1] : '';
                        }
                    }
                }
                switch ($_SERVER['REQUEST_METHOD']) {
                    case 'GET':

                        $data = array_merge($tmp, $_GET, $data, $path_param);

                        break;
                    case 'POST':

                        $data = array_merge($tmp, $_POST, $data, $path_param);

                        break;
                    case 'HEAD':
                        break;
                    case 'PUT':
                        break;
                }
            }
            /*----如果绑定了子域名和模块则先判断绑定模块----end*/
        } else {
            /*----如果绑定了子域名和模块则先判断绑定模块----start*/
            if ((!$reg_status) && self::$subDomainDeploy) {
                $rules = self::$subDomainRules;
                if (isset($rules[$_SERVER['HTTP_HOST']])) { // 完整域名或者IP配置
                    $rule = $rules[$_SERVER['HTTP_HOST']];
                } else {
                    if (strpos(self::$domainSuffix, '.')) { // com.cn net.cn
                        $domain = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -3);
                    } else {
                        $domain = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -2);
                    }
                    if (!empty($domain)) {
                        $subDomain = implode('.', $domain);
                        $domain2 = array_pop($domain); // 二级域名
                        if ($domain) { // 存在三级域名
                            $domain3 = array_pop($domain);
                        }
                        if (isset($rules[$subDomain])) { // 子域名
                            $rule = $rules[$subDomain];
                        } elseif (isset($rules['*.' . $domain2]) && !empty($domain3)) { // 泛三级域名
                            $rule = $rules['*.' . $domain2];
                        } elseif (isset($rules['*']) && !empty($domain2) && 'www' != $domain2) { // 泛二级域名
                            $rule = $rules['*'];
                        }
                    }
                }

                if (!empty($rule)) {
                    // 子域名部署规则
                    if (is_array($rule)) {
                        list($rule, $vars) = $rule;
                    }
                    $array = explode('/', $rule);
                    // 模块绑定
                    $data['module'] = array_shift($array);
                }
            }
        }
        $data['app_path'] = self::$app_path;

        return $data;
    }

    /**
     * @param $url
     * @param string $param
     * @param string $domain
     * @return string
     */
    public static function create_url($url, $param = "", $domain = "")
    {

        if ('/' != PATHINFO_DEPR) {
            // 安全替换
            $url = str_replace('/', PATHINFO_DEPR, $url);
        }
        if (!empty($domain)) {
            $domain = rtrim($domain, '/');
        } else {
            $domain = '';
        }

        // 匹配左侧第一位是否为 右斜杠
        if (stripos($url, '/') >= 0) {
            $url = ltrim($url, "/");
        }

        if (PATHINFO_DEPR == '/') {
            $array = explode('/', $url);
        } elseif (PATHINFO_DEPR == '-') {
            $array = explode('-', $url);
        } elseif (PATHINFO_DEPR == '_') {
            $array = explode('_', $url);
        }


        if (count($array) == 1) {

            $controller = array_pop($array);
            if (__MODULE__) {
                //当前模块
                $module = __MODULE__;
            } else {
                // 默认模块
                $module = DEFAULE_MODULE;
            }
        } elseif (count($array) == 2) {

            $controller = !empty($array[1]) ? $array[1] : DEFAULE_CONTROLLER;
            $module = !empty($array[0]) ? $array[0] : DEFAULE_MODULE;
        }


        $paramStr = '';
        if (is_array($param)) {

            foreach ($param as $k => $v) {

                $paramStr .= PATHINFO_DEPR . $k . PATHINFO_DEPR . $v;
            }
            $url = $module . PATHINFO_DEPR . $controller . $paramStr;
        } else {

            $url = $module . PATHINFO_DEPR . $controller . $paramStr;
        }
        $routeFlag = false;
        if ((!empty(self::$route[self::$subDomainVal])) && is_array(self::$route[self::$subDomainVal])) {
            foreach (self::$route[self::$subDomainVal] as $reg => $value) {
                $value1 = preg_replace('#(\{\d*})#', '(.*)', $value);

                if (preg_match("#^$value1$#i", $url, $match)) {

                    $find = [];
                    $replace = [];
                    $newArr = array_splice($match, 1);
                    $routeFlag = true;

                    foreach ($newArr as $k2 => $v2) {
                        $k2 = $k2 + 1;
                        array_push($find, "{" . $k2 . "}");
                        array_push($replace, $v2);

                    }

                    $url = str_replace($find, $replace, $reg);
                }

            }
        }

        if ((!$routeFlag) && self::$subDomainDeploy) {

            $rules = self::$subDomainRules;


            if (isset($rules[$_SERVER['HTTP_HOST']])) { // 完整域名或者IP配置
                $rule = $rules[$_SERVER['HTTP_HOST']];
            } else {
                if (strpos(self::$domainSuffix, '.')) { // com.cn net.cn
                    $domainSubConf = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -3);
                } else {
                    $domainSubConf = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -2);
                }
                if (!empty($domainSubConf)) {
                    $subDomain = implode('.', $domainSubConf);
                    $domain2 = array_pop($domainSubConf); // 二级域名
                    if ($domainSubConf) { // 存在三级域名
                        $domain3 = array_pop($domainSubConf);
                    }

                    if (isset($rules[$subDomain])) { // 子域名

                        $rule = $rules[$subDomain];

                    } elseif (isset($rules['*.' . $domain2]) && !empty($domain3)) { // 泛三级域名
                        $rule = $rules['*.' . $domain2];
                    } elseif (isset($rules['*']) && !empty($domain2) && 'www' != $domain2) { // 泛二级域名

                        $rule = $rules['*'];
                    }
                }
            }
            if (!empty($rule)) {
                $paramStr = '';
                if (is_array($param)) {

                    foreach ($param as $k => $v) {

                        $paramStr .= PATHINFO_DEPR . $k . PATHINFO_DEPR . $v;
                    }
                    $url = $controller . $paramStr;
                } else {

                    $url = $controller . $paramStr;
                }
                if (empty(URL_HTML_SUFFIX)) {
                    return $domain . '/' . $url;
                } else {
                    return $domain . '/' . $url . '.' . URL_HTML_SUFFIX;
                }
            }


        }


        if (empty(URL_HTML_SUFFIX)) {
            return $domain . '/' . $url;
        } else {
            return $domain . '/' . $url . '.' . URL_HTML_SUFFIX;
        }
    }

    public static function getSubDomain()
    {
        if (strpos(self::$domainSuffix, '.')) { // com.cn net.cn
            $domainSubConf = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -3);
        } else {
            $domainSubConf = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -2);
        }
        if (!empty($domainSubConf)) {
            $domainTwo = addslashes(array_pop($domainSubConf));
        }
        $subDomainRules = self::$subDomainRules;
        if (self::$subDomainDeploy && (!empty($subDomainRules))) {
            //获取二级域名的名字
            $routesNameArr = array_keys($subDomainRules);
            if (!empty($routesNameArr)) {
                foreach ($routesNameArr as $rk => $subDomain) {
                    if (strpos($subDomain, '.') === false) {
                        continue;
                    } else {
                        $routesNameArr[$rk] = explode('.', $subDomain)[0];
                    }
                }
            }
        } else {
            $routesNameArr = [];
        }
        if (empty($domainTwo) || $domainTwo === 'www' || (!in_array($domainTwo, $routesNameArr))) {
            return 'default';
        } else {
            return $domainTwo;
        }
    }
}